package com.hxy.network.filter;

import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order;
import org.springframework.util.StringUtils;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.websocket.server.HandshakeRequest;
import java.io.IOException;

/**
 * @description: websocket鉴权拦截器
 * @program: component_code_integration
 * @author: HCY
 * @create: 2022/04/25 17:02
 *
 * 由于使用了@WebFilter，需要在程序的入口类（**Application.java）中引入@ServletComponentScan注解，否则WebFilter不会生效。
 */
@Slf4j
@Order(1)
@WebFilter(filterName = "websocketFilter", urlPatterns = "/socket/*")
public class WebsocketFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletResponse resp = (HttpServletResponse) response;
        HttpServletRequest req = (HttpServletRequest) request;
        String token = req.getHeader(HandshakeRequest.SEC_WEBSOCKET_PROTOCOL);
        log.info("WS:HEADER-TOKEN:{}", token);
        // 权限校验
        String checkResult = checkToken(token);
        if (!StringUtils.isEmpty(checkResult)) {
            resp.setCharacterEncoding("UTF-8");
            resp.setContentType("application/json; charset=utf-8");
            resp.getWriter().write("WS权限校验失败:" + checkResult);
            resp.getWriter().flush();
            log.error("WS:鉴权失败:{}", checkResult);
            return;
        }
        // response中也要将token信息返回，否则连接建立失败
        resp.setHeader(HandshakeRequest.SEC_WEBSOCKET_PROTOCOL, token);
        chain.doFilter(request, response);
    }

    /**
     * 校验token
     * @param token
     * @return
     */
    private String checkToken(String token) {
        if (StringUtils.isEmpty(token)) {
            return "缺少TOKEN信息";
        }
        // 在这里做token校验
        if (!"asdfghjkl".equals(token)) {
            return "TOKEN失效";
        }
        return null;
    }
}
